package com.foodorder.service;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.foodorder.entity.Order;
import com.foodorder.repository.OrderRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

/**
 * 支付服务
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class PaymentService {

    private final OrderRepository orderRepository;
    private final OrderService orderService;
    private final ObjectMapper objectMapper;
    
    @Value("${wechat.pay.appId:wx123456789}")
    private String wxAppId;
    
    @Value("${wechat.pay.mchId:1234567890}")
    private String wxMchId;
    
    @Value("${wechat.pay.key:testkey123456}")
    private String wxPayKey;
    
    @Value("${wechat.pay.notifyUrl:http://localhost:8080/api/payments/notify/wechat_pay}")
    private String wxNotifyUrl;
    
    /**
     * 准备支付参数
     */
    public Map<String, Object> preparePayment(Long orderId, String method) {
        // 查询订单
        Order order = orderRepository.findById(orderId)
                .orElseThrow(() -> new RuntimeException("订单不存在: " + orderId));
        
        // 验证订单状态
        if (order.getStatus() != Order.OrderStatus.PENDING_PAYMENT) {
            throw new RuntimeException("订单状态不正确: " + order.getStatus());
        }
        
        log.info("准备支付参数: 订单号={}, 金额={}, 支付方式={}", 
                order.getOrderNo(), order.getTotalAmount(), method);
        
        // 根据支付方式生成不同的支付参数
        if ("WECHAT_PAY".equals(method)) {
            return generateWxPayParams(order);
        } else if ("ALIPAY".equals(method)) {
            return generateAlipayParams(order);
        } else {
            throw new RuntimeException("不支持的支付方式: " + method);
        }
    }
    
    /**
     * 生成微信支付参数
     */
    private Map<String, Object> generateWxPayParams(Order order) {
        // 这里简化处理，实际项目中需要接入真实的微信支付API
        String nonceStr = generateNonceStr();
        String prepayId = "wx" + System.currentTimeMillis();
        
        // 模拟计算签名，实际项目中按微信支付文档要求进行签名
        String sign = mockSign(order.getOrderNo(), order.getTotalAmount().toString(), nonceStr);
        
        // 返回支付参数
        Map<String, Object> payParams = new HashMap<>();
        payParams.put("appId", wxAppId);
        payParams.put("timeStamp", String.valueOf(System.currentTimeMillis() / 1000));
        payParams.put("nonceStr", nonceStr);
        payParams.put("package", "prepay_id=" + prepayId);
        payParams.put("signType", "MD5");
        payParams.put("paySign", sign);
        
        log.info("生成微信支付参数成功: {}", payParams);
        return payParams;
    }
    
    /**
     * 生成支付宝支付参数
     */
    private Map<String, Object> generateAlipayParams(Order order) {
        // 实际项目中需要接入真实的支付宝API
        Map<String, Object> payParams = new HashMap<>();
        payParams.put("orderId", order.getId());
        payParams.put("orderNo", order.getOrderNo());
        payParams.put("amount", order.getTotalAmount());
        payParams.put("subject", "餐饮订单-" + order.getOrderNo());
        payParams.put("notifyUrl", "http://localhost:8080/api/payments/notify/alipay");
        
        log.info("生成支付宝支付参数成功: {}", payParams);
        return payParams;
    }
    
    /**
     * 处理支付回调通知
     */
    @Transactional
    public boolean handlePaymentNotify(String paymentMethod, String notifyData) {
        try {
            log.info("处理支付回调: 支付方式={}, 回调数据长度={}", paymentMethod, notifyData.length());
            
            // 解析回调数据
            Map<String, Object> notifyMap = parseNotifyData(paymentMethod, notifyData);
            
            // 校验回调数据
            if (!verifyNotifyData(paymentMethod, notifyMap)) {
                log.warn("支付回调数据验证失败");
                return false;
            }
            
            // 获取订单信息
            String orderNo = getOrderNoFromNotify(paymentMethod, notifyMap);
            Order order = orderRepository.findByOrderNo(orderNo)
                    .orElseThrow(() -> new RuntimeException("订单不存在: " + orderNo));
            
            // 判断支付状态
            boolean isPaid = isPaymentSuccessful(paymentMethod, notifyMap);
            if (!isPaid) {
                log.warn("支付未成功: {}", notifyMap);
                return false;
            }
            
            // 获取交易ID
            String transactionId = getTransactionIdFromNotify(paymentMethod, notifyMap);
            
            // 确认支付
            orderService.confirmPayment(order.getId(), paymentMethod, transactionId);
            
            log.info("支付回调处理成功: 订单号={}, 交易号={}", orderNo, transactionId);
            return true;
            
        } catch (Exception e) {
            log.error("处理支付回调失败: {}", e.getMessage(), e);
            return false;
        }
    }
    
    /**
     * 解析回调数据
     */
    private Map<String, Object> parseNotifyData(String paymentMethod, String notifyData) {
        try {
            if ("WECHAT_PAY".equals(paymentMethod)) {
                // 微信支付回调是XML格式，这里简化处理
                // 实际项目中需要解析XML
                return objectMapper.readValue(notifyData, Map.class);
            } else if ("ALIPAY".equals(paymentMethod)) {
                // 支付宝回调是表单参数
                return objectMapper.readValue(notifyData, Map.class);
            } else {
                throw new RuntimeException("不支持的支付方式: " + paymentMethod);
            }
        } catch (Exception e) {
            log.error("解析回调数据失败: {}", e.getMessage(), e);
            throw new RuntimeException("解析回调数据失败", e);
        }
    }
    
    /**
     * 验证回调数据
     */
    private boolean verifyNotifyData(String paymentMethod, Map<String, Object> notifyMap) {
        // 实际项目中需要对回调数据进行签名验证
        // 这里简化处理，直接返回true
        return true;
    }
    
    /**
     * 从回调数据中获取订单号
     */
    private String getOrderNoFromNotify(String paymentMethod, Map<String, Object> notifyMap) {
        if ("WECHAT_PAY".equals(paymentMethod)) {
            return (String) notifyMap.getOrDefault("out_trade_no", "");
        } else if ("ALIPAY".equals(paymentMethod)) {
            return (String) notifyMap.getOrDefault("out_trade_no", "");
        } else {
            throw new RuntimeException("不支持的支付方式: " + paymentMethod);
        }
    }
    
    /**
     * 从回调数据中获取交易ID
     */
    private String getTransactionIdFromNotify(String paymentMethod, Map<String, Object> notifyMap) {
        if ("WECHAT_PAY".equals(paymentMethod)) {
            return (String) notifyMap.getOrDefault("transaction_id", "");
        } else if ("ALIPAY".equals(paymentMethod)) {
            return (String) notifyMap.getOrDefault("trade_no", "");
        } else {
            throw new RuntimeException("不支持的支付方式: " + paymentMethod);
        }
    }
    
    /**
     * 判断支付是否成功
     */
    private boolean isPaymentSuccessful(String paymentMethod, Map<String, Object> notifyMap) {
        if ("WECHAT_PAY".equals(paymentMethod)) {
            return "SUCCESS".equals(notifyMap.get("result_code"));
        } else if ("ALIPAY".equals(paymentMethod)) {
            return "TRADE_SUCCESS".equals(notifyMap.get("trade_status")) || 
                   "TRADE_FINISHED".equals(notifyMap.get("trade_status"));
        } else {
            throw new RuntimeException("不支持的支付方式: " + paymentMethod);
        }
    }
    
    /**
     * 查询支付状态
     */
    public Map<String, Object> queryPaymentStatus(Long orderId) {
        Order order = orderRepository.findById(orderId)
                .orElseThrow(() -> new RuntimeException("订单不存在: " + orderId));
        
        Map<String, Object> result = new HashMap<>();
        result.put("orderId", order.getId());
        result.put("orderNo", order.getOrderNo());
        result.put("status", order.getStatus());
        result.put("amount", order.getTotalAmount());
        
        if (order.getStatus() == Order.OrderStatus.PAID || 
            order.getStatus() == Order.OrderStatus.PROCESSING || 
            order.getStatus() == Order.OrderStatus.DELIVERING || 
            order.getStatus() == Order.OrderStatus.COMPLETED) {
            result.put("paid", true);
            result.put("paymentMethod", order.getPaymentMethod());
            result.put("paymentTime", order.getPaidAt());
            result.put("transactionId", order.getPaymentTransactionId());
        } else {
            result.put("paid", false);
        }
        
        return result;
    }
    
    /**
     * 关闭支付
     */
    @Transactional
    public boolean closePayment(Long orderId) {
        Order order = orderRepository.findById(orderId)
                .orElseThrow(() -> new RuntimeException("订单不存在: " + orderId));
        
        // 只有待支付状态的订单才能关闭支付
        if (order.getStatus() != Order.OrderStatus.PENDING_PAYMENT) {
            throw new RuntimeException("订单状态不正确: " + order.getStatus());
        }
        
        try {
            // 这里应该调用支付平台的关闭订单接口
            // 但由于是模拟实现，直接取消订单即可
            orderService.cancelOrder(orderId, "用户取消支付");
            
            log.info("关闭支付成功: 订单ID={}", orderId);
            return true;
        } catch (Exception e) {
            log.error("关闭支付失败: {}", e.getMessage(), e);
            return false;
        }
    }
    
    /**
     * 申请退款
     */
    @Transactional
    public Map<String, Object> refundPayment(Long orderId, Double amount, String reason) {
        Order order = orderRepository.findById(orderId)
                .orElseThrow(() -> new RuntimeException("订单不存在: " + orderId));
        
        // 验证订单状态，只有已支付、处理中、配送中的订单可以退款
        if (order.getStatus() != Order.OrderStatus.PAID && 
            order.getStatus() != Order.OrderStatus.PROCESSING && 
            order.getStatus() != Order.OrderStatus.DELIVERING) {
            throw new RuntimeException("订单状态不支持退款: " + order.getStatus());
        }
        
        // 验证退款金额
        if (amount > order.getTotalAmount().doubleValue()) {
            throw new RuntimeException("退款金额不能大于订单金额");
        }
        
        // 生成退款单号
        String refundNo = "REF" + System.currentTimeMillis() + UUID.randomUUID().toString().substring(0, 4).toUpperCase();
        
        try {
            // 实际项目中需要调用支付平台的退款接口
            // 这里是模拟实现
            
            // 更新订单状态为已取消
            orderService.cancelOrder(orderId, reason);
            
            // 返回退款结果
            Map<String, Object> result = new HashMap<>();
            result.put("orderId", orderId);
            result.put("orderNo", order.getOrderNo());
            result.put("refundNo", refundNo);
            result.put("refundAmount", amount);
            result.put("reason", reason);
            result.put("refundTime", LocalDateTime.now());
            result.put("status", "SUCCESS");
            
            log.info("申请退款成功: 订单ID={}, 退款金额={}, 原因={}", orderId, amount, reason);
            return result;
        } catch (Exception e) {
            log.error("申请退款失败: {}", e.getMessage(), e);
            throw new RuntimeException("申请退款失败: " + e.getMessage());
        }
    }
    
    /**
     * 生成随机字符串
     */
    private String generateNonceStr() {
        return UUID.randomUUID().toString().replaceAll("-", "").substring(0, 16);
    }
    
    /**
     * 模拟签名
     */
    private String mockSign(String orderNo, String amount, String nonceStr) {
        // 实际项目中需要按照支付平台的规则进行签名
        // 这里简化处理，模拟签名
        String content = orderNo + amount + nonceStr + wxPayKey;
        return UUID.nameUUIDFromBytes(content.getBytes()).toString().replaceAll("-", "");
    }
} 